import net.biancheng.po.*;
import net.biancheng.po.Class;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class test {



    int all=0;//所有班级课程的数量
    List<Class> classes=new ArrayList<>();//班级
    List<Classroom>  classrooms=new ArrayList<>();//教室
    List<Schedule> schedules=new ArrayList<>();//课表
    List<Course> courses=new ArrayList<>();//课程
    Plan plan;//课程计划
    List<Teacher> teachers=new ArrayList<>();//教师
    Tool atool=new Tool();//工具类
    PieceSchedule pieceSchedules[];//课表的细分，代表的是班级、课程、教室、教师


    @Test
    public void main(){
        init();//初始化，配置优先级等

        if(!fixAuto()) {//判断教室是否足够
            System.out.println("教室不够用，排课结束");
            return;
        }else
            System.out.println("教室足够，开始排课...");
        pieceSchedules=new PieceSchedule[all];

        if(!auto()) {
            System.out.println("排课教师资源不足");//自动排课
            return ;
        }

        trans();//转换

        prin();//打印课表
    }

    public void init(){//初始化赋值，20个班、一个班一周10节课，一个Schcedules对应一个班
        System.out.println("初始化中....");
        System.out.println();

//        classes = new Classes[20];//20个班级
//        classrooms=new Classroom[20];//20个教室
//        schedules=new Schedule[classes.length];//20个班级对应20个课表
//        courses=new Course[10];//10种课程
//        teachers=new Teacher[5];//5个教师
        plan=new Plan();

        for(int i=0;i<10;i++){//设置课程
            Course course=new Course();
            course.setCourseno(i+20);//设置课程编号
            course.setPri(i%5+5);//设置课程单独优先级
            course.setType(i+10);//课程类型以int表示
            course.setNature(i%2);//0为理论，1为实践
            courses.add(i,course);
        }
        System.out.println();

        int temp=0;
        for(int i=0;i<30;i++) {//设置教师，课程与教师关系
            if(temp==10) temp=0;
            Teacher teacher=new Teacher();
            teacher.setAccount(i+50);
            teacher.setTeacherTime();//初始化没上课
//            teacher.setCourseN(2);//1个教师教2门课
            teacher.setCourseNo(0,courses.get(temp).getCourseno());//设置课程

//            courses[temp].setTeacherN(1);//1个教师教
            courses.get(temp).setTeacherNo(0,teacher.getAccount());//设置教师

            temp+=1;
            teacher.setCourseNo(1,courses.get(temp).getCourseno());//设置课程

//            courses[temp].setTeacherN(1);//1个教师教
            courses.get(temp).setTeacherNo(0,teacher.getAccount());//设置教师
            temp+=1;
            teachers.add(i,teacher);
            System.out.println(teachers.get(i).toString());
        }

        atool.setCourses(courses);//设置工具的课程
        atool.setTeachers(teachers);//设置工具的教师
        System.out.println();

        plan.setPlanno(1);//所有班级用一个计划
//        plan.setCoursesN(10);
        for(int j=0;j<10;j++) {//课程
            plan.setCourses(j,courses.get(j).getCourseno());
            System.out.println(courses.get(j).toString());
        }
        System.out.println();

        for(int i=0;i<20;i++){//设置课表和班级
            Class ccc=new Class();
            ccc.setClassno(i);//班级编号
            if(i%2==0)//设置班级人数
                ccc.setPeople(50);
            else
                ccc.setPeople(30);
            classes.add(i,ccc);
            atool.setClasses(classes);

            Schedule s=new Schedule(atool,plan);
            s.setClassNo(classes.get(i).getClassno());
            s.setPeople(classes.get(i).getPeople());
            s.addPri();//这一步自动设置pieceSchedule
//        pieceSchedules=new PieceSchedule[plan.getCourses().length];//设置课程数量
            schedules.add(i,s);
            System.out.println(schedules.get(i).toString());
        }
        System.out.println();

        for(int i=0;i<30;i++){//初始化教室的所有节次没有被占用
            Classroom cccr=new Classroom();
            cccr.setClassNum();//都为false
            cccr.setRoomno(i+100);//教室编号
            if(i%2==0)//设置班级人数
                cccr.setHold(40);
            else
                cccr.setHold(60);
            cccr.setRoomtype(i%2);//设置教室类型
            classrooms.add(i,cccr);
            System.out.println(classrooms.get(i).toString());
        }
        System.out.println();
    }//初始化完成后，各课表对应班级、课程和教室都已就绪

    public boolean fixAuto(){//查看教室数量是否足够
        int cccr=classrooms.size()*35;//所有教室可上节次数量

        for(int i=0;i<schedules.size();i++)
            all=all+schedules.get(i).getPieceSchedules().size();
        System.out.println("教室数量："+cccr+"课程节次："+all);
        if(cccr<all) return false;
        return true;
    }

    public void trans(){//将单独的pieceSchedule导入schedules
        for(PieceSchedule p:pieceSchedules){
            for (Schedule s:schedules)
                for(PieceSchedule pp:s.getPieceSchedules()){
                    if(p.getCourseno()==pp.getCourseno() && p.getClassno()==pp.getClassno()){//根据班级和课程赋值
                        pp.setSection(p.getSection());//设置时间、教室、教师
                        pp.setRoomno(p.getRoomno());
                        pp.setTeacherno(p.getTeacherno());
                    }
                }
        }
    }

    public void prin(){
        for(int i=0;i<schedules.size();i++) {//遍历所有的班级课表
            List<PieceSchedule> pieceSchedules=schedules.get(i).getPieceSchedules();
            int c=schedules.get(i).getClassNo();
            System.out.println("班级"+c+"课表如下：");//打印班级编号
            for(int j=0;j<pieceSchedules.size();j++){//打印课程和对应的时间、教室
                PieceSchedule p=pieceSchedules.get(j);
                System.out.println(p.toString());
            }
            System.out.println("班级"+c+"打印完成");
            System.out.println();
            System.out.println();
            System.out.println();
        }
        for(Classroom c:classrooms)
            System.out.println(c.toString());
    }

    public boolean auto(){//模拟退火算法
        int y[]= {1,3,2,4,0};
        int day[]= {8,8,8,8,8,8,8};
        int count=0;
        while(true){//随机天数
            int temp=(int)(Math.random()*(7));
            boolean b=false;
            for(int x=0;x<7;x++){
                if(day[x]==temp){
                    b=true;
                    break;
                }
            }
            if(!b) day[count++]=temp;
            if(count==7) break;
        }
        System.out.println(Arrays.toString(day));
        count=0;
        while(count++<classrooms.size()){//随机教室20次
            int temp1=(int)(Math.random()*(classrooms.size()));
            int temp2=(int)(Math.random()*(classrooms.size()));
            Classroom c1= classrooms.get(temp1);
            classrooms.set(temp1,classrooms.get(temp2));
            classrooms.set(temp2,c1);
        }
        System.out.println(classrooms);
        atool.addPiece(pieceSchedules,schedules);//添加所有班级课程，并排序
        for(PieceSchedule p:pieceSchedules){//遍历所有的课程
            List<Integer> Teacherno=atool.findTeacherNo(p.getCourseno());//获取教这门课的老师
            if(p.getRoomno()==0) {//如果这个课程没有排课
                for(int z=0;z<4;z++){//从每天第二节开始
                    for(int i=0;i<7;i++) {//天数，随机
                        int time=y[z]+day[i]*5;//时间0-34
                        for (int k=0;k<classrooms.size();k++) {//寻找教室,已随机.
                            int tt= (int)(Math.random()*(Teacherno.size()));//随机教师
                            Classroom c=classrooms.get(k);//已随机
                            if (!c.getClassNum(time) && c.getHold()>atool.findClassP(p.getClassno())) {
                                //&& c.getRoomtype()==atool.findCtype(p.getCourseno())
                                //如果教室没上课、人数可容纳、类型一致
                                boolean teatime=atool.checkTeacher(Teacherno.get(tt),time);
                                if(teatime)
                                    break;//如果教师有课就换一天
                                atool.setTeacher(Teacherno.get(tt),time);//设置教师time时间有课
                                p.setTeacherno(Teacherno.get(tt));//课表设置教师
                                p.setRoomno(c.getRoomno());//设置课表的课程教室号
                                p.setSection(time);//设置课表的课程时间
                                c.setClassNum(time, true);//该教室在time时间有课

                                break;
                            }
                        }
                        if (p.getRoomno()!=0) break;//如果设置了教室就退出查找
                    }
                    if (p.getRoomno()!=0) break;//如果设置了教室就退出查找
                }
            }
            if(p.getRoomno()==0) //如果循环结束还没排课
                return false;
        }
        System.out.println("auto finished");
        return true;
    }


//    public void auto(){//贪心算法
//        for(int i=0;i<schedules.length;i++){//遍历所有的班级课表
//            pieceSchedule[] pieceSchedules=schedules[i].getPieceSchedules();
//            for(int j=0;j<pieceSchedules.length;j++){//遍历这个班级的课程
//                pieceSchedule p=pieceSchedules[j];
//                if(p.getClassroomNum()==0) {//如果这个课程没有排课
////                    System.out.println("查询到没有排课的课程"+p.getCourseno());
//                    for(int k=0;k<classrooms.length;k++){//遍历所有的教室
//                        Classroom c=classrooms[k];
//                        boolean b=false;
//                        for(int z=0;z<35;z++){//遍历c教室z时间有没有上课
//                            if(!c.getClassNum(z)) {//如果没上课
//                                p.setClassroomNum(c.getRoomno());//设置课表的课程教室号
//                                p.setClassroomTime(z);//设置课表的课程时间
//                                c.setClassNum(z,true);//该教室在z时间有课
//                                b=true;
//                                break;
//                            }
//                        }
//                        if(b) break;//如果设置了教室就退出查找
//                    }
//                }
//            }
//        }
//        System.out.println("auto finished");
//    }
}
